//package com.lvt.example.thinking.in.spring.questions.L23.transactional;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
///**
// * desc：class
// *
// * @author LT
// * @date 2022/10/25
// */
//
//
//@Service
//public class StudentService {
//    @Autowired
//    private StudentMapper studentMapper;
//
//    @Autowired
//    private StudentService studentService;
//
//    public void saveStudent(String realname) throws Exception {
//        Student student = new Student();
//        student.setRealname(realname);
//        studentService.doSaveStudent(student);
//    }
//
//    //    @Transactional
//    @Transactional(rollbackFor = Exception.class)
//    // idea 已经能识别，案例 2：试图给 private 方法添加事务
//    /**
//     * 是从 AbstractAutoProxyCreator 里的 postProcessAfterInitialization 方法开始处理的
//     * 我们一路往下找，暂且略过那些非关键要素的代码，直到到了 AopUtils 的 canApply 方法。这个方法就是针对切面定义里的条件，确定这个方法是否可以被应用创建成代理。
//     * 其中有一段 methodMatcher.matches(method, targetClass) 是用来判断这个方法是否符合这样的条件
//     */
////    private void doSaveStudent(Student student) throws Exception {
//    public void doSaveStudent(Student student) throws Exception {
//        studentMapper.saveStudent(student);
//        if (student.getRealname().equals("小明")) {
//            throw new RuntimeException("该用户已存在");
//        }
//    }
//
//    @Autowired
//    private CourseService courseService;
//
//    /**
//     * 最后的结果是，学生和选课的信息都被回滚了，显然这并不符合我们的预期。
//     * 我们期待的结果是即便内部事务 regCourse() 发生异常，外部事务 saveStudent() 俘获该异常后，内部事务应自行回滚，不影响外部事务。
//     *
//     * 看下  Spring 事务处理的核心，其关键实现参考 TransactionAspectSupport.invokeWithinTransaction()
//     */
//    @Transactional(rollbackFor = Exception.class)
//
//    public void saveStudent2(String realname) throws Exception {
//        /**
//         * 因为在 saveStudent() 上声明了一个外部的事务，就已经存在一个事务了，在 propagation 值为默认的 REQUIRED 的情况下，
//         * regCourse() 就会加入到已有的事务中，两个方法共用一个事务。
//         */
//        Student student = new Student();
//        student.setRealname(realname);
//        studentService.doSaveStudent(student);
//        try {
//            courseService.regCourse(student.getId());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//}
